; string.asm
; string manipulation

	.include "common.inc"
	.include "petscii.inc"
	.include "global.inc"

	.export ssetbuf
	.export scopyto
	.export sstr2scr
	.export sgetlen
	.export sgetsize
	.export saddch
	.export saddstr
	.export sputhexb
	.export sputuint
	.export sclear
	.export sscr2str
	.export strim

	.segment "DATA"

idx:		.byte 0
ch:			.byte 0
len:		.byte 0
num:		
numlo:		.byte 0
numhi:		.byte 0
putzero:	.byte 0		

	.segment "RODATA"
	
hexchars:	.byte "0123456789abcdef"

; 10000, 1000, 100, 10
declo:		.byte $10, $E8, $64, $0A
dechi:		.byte $27, $03, $00, $00

	.segment "CODE"
	
ssetbuf:	; A/X ... ptr to buffer (size, len, buf)
			sta strptr
			stx strptr+1
			rts

sputuint:	; buf ptr from ssetbuf, A/X .. UINT
			sta numlo
			stx numhi
			ldx #0
			stx putzero
@nxtdig:	ldy #0
@lpdig:		lda numhi
			cmp dechi, x
			bcc @dndig
			bne @dodig
			lda numlo
			cmp declo, x
			bcc @dndig
@dodig:		iny
			sec
			lda numlo
			sbc declo, x
			sta numlo
			lda numhi
			sbc dechi, x
			sta numhi
			bcs @lpdig
@dndig:		tya
			ora putzero
			beq @dnout		; TODO: Skip '0' only if not first digit
			inc putzero
			tya
			clc
			adc #$30
			jsr saddch
@dnout:		inx
			cpx #4
			bcc @nxtdig
			lda numlo
			clc
			adc #$30
			jmp saddch
	
sclear:		; buf ptr from ssetbuf
			ldy #String::len
			lda #0
			sta (strptr), y
			rts	

sstr2scr:	; buf ptr from ssetbuf, A/Y .. scratch
			ldy #String::len
			lda (strptr), y
			beq @done
			sta idx
@next:		iny
			lda (strptr), y
			jsr pet2scr
			sta (strptr), y
			dec idx
			bne @next
@done:		rts

sscr2str:	; buf ptr from ssetbuf, A/Y .. scratch
			ldy #String::len
			lda (strptr), y
			beq @done
			sta idx
@next:		iny
			lda (strptr), y
			jsr scr2pet
			sta (strptr), y
			dec idx
			bne @next
@done:		rts

sgetlen:	; buf ptr from ssetbuf -> A ... strlen, Y .. scratch
			ldy #String::len
			lda (strptr), y
			rts
			
sgetsize:	; buf ptr from ssetbuf -> A ... strlen, Y .. scratch
			ldy #String::size
			lda (strptr), y
			rts

saddch:		; buf ptr from ssetbuf, A ... char to add, Y .. scratch
			; -> X .. unchanged! (Carry = 1, failed)
			sta ch
			ldy #String::len
			lda (strptr), y
			ldy #String::size
			cmp (strptr), y
			bcs @done
			adc #1
			ldy #String::len
			sta (strptr), y
			adc #String::data-1
			tay
			lda ch
			sta (strptr), y
			clc
@done:		rts

sputhexb:	; buf ptr from ssetbuf, A .. byte to add as hex number
			sta num
			lsr
			lsr
			lsr
			lsr
			tax
			lda hexchars, x
			jsr saddch
			lda num
			and #$0F
			tax
			lda hexchars, x
			jmp saddch

	.segment "DATA"		; self-modifying code

scopyto:	; copies current contents to buffer (size byte + string)
			; A/X ... ptr to target buffer, Y ... scratch
			sta @dst+1
			stx @dst+2
			ldy #String::len
			lda (strptr), y
			tay
			iny
@cploop:	lda (strptr), y
			dey
@dst:		sta $FFFF, y
			bne @cploop
			rts

	.segment "CODE"

saddstr:	; adds string in buffer to current string
			; buf ptr from ssetbuf, A/X ... string data to add (first byte .. length)
			sta strptr2
			stx strptr2+1
			ldy #0
			lda (strptr2), y
			sta len
			sty idx
			ldx len
			beq @done
@addloop:	inc idx
			ldy idx
			lda (strptr2), y
			jsr saddch
			dex
			bne @addloop		
@done:		rts

strim:		; removes trailing spaces from string
			ldy #String::len
			lda (strptr), y
			beq @done
			clc
			adc #String::data-1
			tay
			lda #32		; space
@next:		cmp (strptr), y
			bne @stolen
			dey
			cpy #String::data-1
			bne @next
@stolen:	sec
			tya
			sbc #String::data-1
			ldy #String::len
			sta (strptr), y
@done:		rts
